﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EzDesk.Apps.Model.Attendance;
using EzDesk.Apps.UnitTest.Mock;
using EzDesk.EzAppApi.Utility;

namespace EzDesk.Apps.UnitTest
{
    public abstract class AttendanceContextBase<T> : IServiceTestContext<T>
    {
        public abstract T Service { get; }
        
        protected void initAttendanceConfig()
        {
            this._attendanceConfig = new AttendanceConfig
            {
                StdOnDutyTime = new SimpleTime() { Hour = 9, Miniute = 0 },
                StdOffDutyTime = new SimpleTime() { Hour = 18, Miniute = 0 },
                StdOnDutyTimeDelay = TimeSpan.FromMinutes(5),
                OnDutyOffsetForward = TimeSpan.FromMinutes(30),
                OnDutyOffsetAfterward = TimeSpan.FromMinutes(60),
                LunchBreakTime = TimeSpan.FromHours(1),
                StdManhours = TimeSpan.FromHours(8),
            };
        }

        protected AttendanceConfig _attendanceConfig;
        protected Guid _userId;
        protected DayInfo _dayInfo;
        protected int _extraManhours;
        protected DayLeaveInfo _dayLeaveInfo;
        protected List<AttendanceInfo> _attendanceInfoList = new List<AttendanceInfo>();
        protected List<LeaveInfo> _leaveInfos = new List<LeaveInfo>();

        protected IEzApiClient _ezApiClient;
        protected Mock_AttendanceInfoRepository _attendanceInfoRepository;
        protected Mock_LeaveTypeRepository _leaveTypeRepository;
        protected Mock_LeaveInfoRepository _leaveInfoRepository;
        protected Mock_LegalHolidayRepository _legalHolidayRepository;
        protected Mock_ExtraShiftRepository _extraShiftRepository;
        protected Mock_EvaluationModifyApplicationRepository _evaluationApplicationRepository;
        protected Mock_EvaluationModifyHistoryRepository _evaluationModifyHistoryRepository;
        protected Mock_ModifiedEvaluationRepository _modifiedEvaluationRepository;

        private DateTime getActionTimeToDay(string actionTimeString)
        {
            if (actionTimeString.Length > 10)
            {
                return DateTime.Parse(actionTimeString);
            }
            return DateTime.Parse(_dayInfo.Date.ToString("yyyy-MM-dd ") + actionTimeString);
        }


        #region [ Public Methods ]
        public AttendanceContextBase<T> SetupDay(string dayString)
        {
            var theDay = DateTime.Parse(dayString).Date;

            _dayInfo = new DayInfo(theDay);
            return this;
        }

        public AttendanceContextBase<T> SetupAttendanceInfo(
            string actionTimeString,
            string actionTypeString,
            bool isAbnormal)
        {
            AttendanceType attendanceType;
            Enum.TryParse(actionTypeString, true, out attendanceType);

            DateTime actionTime = getActionTimeToDay(actionTimeString);

            var attendanceInfo = new AttendanceInfo()
            {
                ActionTime = actionTime,
                AttendanceType = attendanceType,
                Date = this._dayInfo.Date,
                Explanation = string.Empty,
                Id = Guid.NewGuid(),
                IsAbnormalAttendance = isAbnormal,
                UserId = this._userId
            };

            _attendanceInfoList.Add(attendanceInfo);
            return this;
        }


        public AttendanceContextBase<T> SetupLeaveInfo(
            string leaveyTypeName,
            string startTimeString, 
            string endTimeString, 
            string createTimeString, 
            bool isAudited, bool isAgreed, Guid auditUserId, string auditTimeString)
        {
            if (leaveyTypeName == null) throw new ArgumentNullException("leaveyTypeName");
            DateTime startTime = getActionTimeToDay(startTimeString);
            DateTime endTime = getActionTimeToDay(endTimeString);
            DateTime createTime = getActionTimeToDay(createTimeString);
            var leaveType = _leaveTypeRepository.GetAll().Where(p => p.LeaveTypeName == leaveyTypeName).FirstOrDefault();

            DateTime auditTime = getActionTimeToDay(auditTimeString);
            var leaveInfo = new LeaveInfo()
                                      {
                                          AuditNote = "Test",
                                          CreateTime = createTime,
                                          Description = "TEST Desc",
                                          Id = new Guid(),
                                          StartTime = startTime,
                                          EndTime = endTime,
                                          LeaveTypeId = leaveType.Id,
                                          IsForWork = leaveType.IsForWork,
                                          LeaveTypeName = leaveType.LeaveTypeName,
                                          
                                          AuditTime = auditTime,
                                          AuditUserId = auditUserId,
                                          IsAgreed = isAgreed,
                                          IsAudited = isAudited,
                                      };
            _leaveInfos.Add(leaveInfo);
            return this;
        }

        public AttendanceContextBase<T> SetupLeaveInfoWithNoAudit(
            string leaveyTypeName,
            string startTimeString,
            string endTimeString,
            string createTimeString
        )
        {
            return SetupLeaveInfo(
                leaveyTypeName,
                startTimeString,
                endTimeString,
                createTimeString,
                false,
                false,
                Guid.Empty,
                ""
                );
        }

        public AttendanceContextBase<T> SetupDayLeaveInfo(
            string leaveType, string startTimeString, string endTimeString,
            bool isWholeDay, bool isForWork
            )
        {
            _dayLeaveInfo = new DayLeaveInfo()
            {
                IsWholeDay = isWholeDay,
                Leaves = new List<DayLeaveInfoItem>()
                                                 {
                                                     new DayLeaveInfoItem()
                                                         {
                                                             LeaveName = leaveType,
                                                             StartTime = getActionTimeToDay(startTimeString),
                                                             EndTime = getActionTimeToDay(endTimeString),
                                                             IsForWork = isForWork
                                                         }
                                                 }

            };

            return this;
        }
        #endregion

    }
}
